home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / winsr173.zip / HELPCOM.H < prev    next >
Text File  |  1991-04-17  |  16KB  |  781 lines

  1.  
  2. /*
  3.  * helpcom.h
  4.  *
  5.  *
  6.  * Common #defines, structures and code for HC.C and HELP.C
  7.  *
  8.  */
  9.  
  10.  
  11. /*
  12.  * help file signature
  13.  */
  14.  
  15. #define HELP_SIG       (0xAFBC1823LU)
  16.  
  17.  
  18. /*
  19.  * commands imbedded in the help text
  20.  */
  21.  
  22. #define CMD_LITERAL      1   /* next char taken literally */
  23. #define CMD_PARA      2   /* paragraph start code */
  24. #define CMD_LINK      3   /* hot-link start/end code */
  25. #define CMD_FF          4   /* force a form-feed */
  26. #define CMD_XONLINE      5   /* exclude from online help on/off */
  27. #define CMD_XDOC      6   /* exclude from printed document on/off */
  28. #define CMD_CENTER      7   /* center this line */
  29. #define CMD_SPACE      8   /* next byte is count of spaces */
  30.  
  31. #define MAX_CMD       8
  32.  
  33.  
  34. /*
  35.  * on-line help dimensions
  36.  */
  37.  
  38. #define SCREEN_WIDTH      (78)
  39. #define SCREEN_DEPTH      (22)
  40. #define SCREEN_INDENT      (1)
  41.  
  42.  
  43. /*
  44.  * printed document dimensions
  45.  */
  46.  
  47. #define PAGE_WIDTH       (72)  /* width of printed text */
  48. #define PAGE_INDENT       (2)     /* indent all text by this much */
  49. #define TITLE_INDENT       (1)     /* indent titles by this much */
  50.  
  51. #define PAGE_RDEPTH       (59)  /* the total depth (inc. heading) */
  52. #define PAGE_HEADING_DEPTH (3)     /* depth of the heading */
  53. #define PAGE_DEPTH       (PAGE_RDEPTH-PAGE_HEADING_DEPTH) /* depth of text */
  54.  
  55.  
  56. /*
  57.  * Document page-break macros.    Goto to next page if this close (or closer)
  58.  * to end of page when starting a CONTENT, TOPIC, or at a BLANK line.
  59.  */
  60.  
  61. #define CONTENT_BREAK (7)  /* start of a "DocContent" entry */
  62. #define TOPIC_BREAK   (4)  /* start of each topic under a DocContent entry */
  63. #define BLANK_BREAK   (2)  /* a blank line */
  64.  
  65.  
  66. /*
  67.  * tokens returned by find_token_length
  68.  */
  69.  
  70. #define TOK_DONE    (0)   /* len == 0          */
  71. #define TOK_SPACE   (1)   /* a run of spaces      */
  72. #define TOK_LINK    (2)   /* an entire link      */
  73. #define TOK_PARA    (3)   /* a CMD_PARA       */
  74. #define TOK_NL        (4)   /* a new-line ('\n')    */
  75. #define TOK_FF        (5)   /* a form-feed (CMD_FF) */
  76. #define TOK_WORD    (6)   /* a word          */
  77. #define TOK_XONLINE (7)   /* a CMD_XONLINE      */
  78. #define TOK_XDOC    (8)   /* a CMD_XDOC       */
  79. #define TOK_CENTER  (9)   /* a CMD_CENTER      */
  80.  
  81.  
  82. /*
  83.  * modes for find_token_length() and find_line_width()
  84.  */
  85.  
  86. #define ONLINE 1
  87. #define DOC    2
  88.  
  89.  
  90. /*
  91.  * struct PD_INFO used by process_document()
  92.  */
  93.  
  94. typedef struct
  95.    {
  96.  
  97.    /* used by process_document -- look but don't touch! */
  98.  
  99.    int         pnum,
  100.          lnum;
  101.  
  102.    /* PD_GET_TOPIC is allowed to change these */
  103.  
  104.    char far *curr;
  105.    unsigned  len;
  106.  
  107.    /* PD_GET_CONTENT is allowed to change these */
  108.  
  109.    char far *id;
  110.    char far *title;
  111.    int         new_page;
  112.  
  113.    /* general parameters */
  114.  
  115.    char far *s;
  116.    int         i;
  117.  
  118.  
  119.    } PD_INFO;
  120.  
  121.  
  122. /*
  123.  * Commands passed to (*get_info)() and (*output)() by process_document()
  124.  */
  125.  
  126. enum  PD_COMMANDS
  127.    {
  128.  
  129. /* commands sent to pd_output */
  130.  
  131.    PD_HEADING,           /* call at the top of each page */
  132.    PD_FOOTING,        /* called at the end of each page */
  133.    PD_PRINT,        /* called to send text to the printer */
  134.    PD_PRINTN,        /* called to print a char n times */
  135.    PD_PRINT_SEC,    /* called to print the section title line */
  136.    PD_START_SECTION,    /* called at the start of each section */
  137.    PD_START_TOPIC,    /* called at the start of each topic */
  138.    PD_SET_SECTION_PAGE, /* set the current sections page number */
  139.    PD_SET_TOPIC_PAGE,    /* set the current topics page number */
  140.    PD_PERIODIC,     /* called just before curr is incremented to next token */
  141.  
  142. /* commands sent to pd_get_info */
  143.  
  144.    PD_GET_CONTENT,
  145.    PD_GET_TOPIC,
  146.    PD_RELEASE_TOPIC,
  147.    PD_GET_LINK_PAGE
  148.  
  149.    } ;
  150.  
  151.  
  152. typedef int (*PD_FUNC)(int cmd, PD_INFO *pd, void *info);
  153.  
  154.  
  155. int _find_token_length(char far *curr, unsigned len, int *size, int *width);
  156. int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width);
  157. int find_line_width(int mode, char far *curr, unsigned len);
  158. int process_document(PD_FUNC get_info, PD_FUNC output, void *info);
  159.  
  160.  
  161. /*
  162.  * Code common to both HC.C and HELP.C (in Fractint).
  163.  * #include INCLUDE_COMMON once for each program
  164.  */
  165.  
  166.  
  167. #ifdef INCLUDE_COMMON
  168.  
  169.  
  170. static int is_hyphen(char far *ptr)   /* true if ptr points to a real hyphen */
  171.    {                   /* checkes for "--" and " -" */
  172.    if ( *ptr != '-' )
  173.       return (0);    /* that was easy! */
  174.  
  175.    --ptr;
  176.  
  177.    return ( *ptr!=' ' && *ptr!='-' );
  178.    }
  179.  
  180.  
  181. int _find_token_length(register char far *curr, unsigned len, int *size, int *width)
  182.    {
  183.    register int _size  = 0;
  184.    register int _width = 0;
  185.    int tok;
  186.  
  187.    if (len == 0)
  188.       tok = TOK_DONE;
  189.  
  190.    else
  191.       {
  192.       switch ( *curr )
  193.      {
  194.      case ' ':    /* it's a run of spaces */
  195.         tok = TOK_SPACE;
  196.         while ( *curr == ' ' && _size < len )
  197.            {
  198.            ++curr;
  199.            ++_size;
  200.            ++_width;
  201.            }
  202.         break;
  203.  
  204.      case CMD_SPACE:
  205.         tok = TOK_SPACE;
  206.         ++curr;
  207.         ++_size;
  208.         _width = *curr;
  209.         ++curr;
  210.         ++_size;
  211.         break;
  212.  
  213.      case CMD_LINK:
  214.         tok = TOK_LINK;
  215.         _size += 7;     /* skip CMD_LINK + topic_num + topic_off + page_num */
  216.         curr += 7;
  217.  
  218.         while ( *curr != CMD_LINK )
  219.            {
  220.            if ( *curr == CMD_LITERAL )
  221.           {
  222.           ++curr;
  223.           ++_size;
  224.           }
  225.            ++curr;
  226.            ++_size;
  227.            ++_width;
  228.            assert(_size < len);
  229.            }
  230.  
  231.         ++_size;   /* skip ending CMD_LINK */
  232.         break;
  233.  
  234.      case CMD_PARA:
  235.         tok = TOK_PARA;
  236.         _size += 3;     /* skip CMD_PARA + indent + margin */
  237.         break;
  238.  
  239.      case CMD_XONLINE:
  240.         tok = TOK_XONLINE;
  241.         ++_size;
  242.         break;
  243.  
  244.      case CMD_XDOC:
  245.         tok = TOK_XDOC;
  246.         ++_size;
  247.         break;
  248.  
  249.      case CMD_CENTER:
  250.         tok = TOK_CENTER;
  251.         ++_size;
  252.         break;
  253.  
  254.      case '\n':
  255.         tok = TOK_NL;
  256.         ++_size;
  257.         break;
  258.  
  259.      case CMD_FF:
  260.         tok = TOK_FF;
  261.         ++_size;
  262.         break;
  263.  
  264.      default:   /* it must be a word */
  265.         tok = TOK_WORD;
  266.         while (1)
  267.            {
  268.            if ( _size >= len )
  269.           break;
  270.  
  271.            else if ( *curr == CMD_LITERAL )
  272.           {
  273.           curr += 2;
  274.           _size += 2;
  275.           _width += 1;
  276.           }
  277.  
  278.            else if ( *curr == '\0' )
  279.           {
  280.           assert(0);
  281.           }
  282.  
  283.            else if ((unsigned)*curr <= MAX_CMD || *curr == ' ' ||
  284.             *curr == '\n')
  285.           break;
  286.  
  287.            else if ( *curr == '-' )
  288.           {
  289.           ++curr;
  290.           ++_size;
  291.           ++_width;
  292.           if ( is_hyphen(curr-1) )
  293.              break;
  294.           }
  295.  
  296.            else
  297.           {
  298.           ++curr;
  299.           ++_size;
  300.           ++_width;
  301.           }
  302.            }
  303.         break;
  304.      } /* switch */
  305.       }
  306.  
  307.    if (size  != NULL)    *size  = _size;
  308.    if (width != NULL)    *width = _width;
  309.  
  310.    return (tok);
  311.    }
  312.  
  313.  
  314. int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width)
  315.    {
  316.    int tok;
  317.    int t;
  318.    int _size;
  319.  
  320.    tok = _find_token_length(curr, len, &t, width);
  321.  
  322.    if ( (tok == TOK_XONLINE && mode == ONLINE) ||
  323.     (tok == TOK_XDOC    && mode == DOC)     )
  324.       {
  325.       _size = 0;
  326.  
  327.       while (1)
  328.      {
  329.      curr  += t;
  330.      len   -= t;
  331.      _size += t;
  332.  
  333.      tok = _find_token_length(curr, len, &t, NULL);
  334.  
  335.      if ( (tok == TOK_XONLINE && mode == ONLINE) ||
  336.           (tok == TOK_XDOC      && mode == DOC)    ||
  337.           (tok == TOK_DONE)                )
  338.         break;
  339.      }
  340.  
  341.       _size += t;
  342.       }
  343.    else
  344.       _size = t;
  345.  
  346.    if (size != NULL )
  347.       *size = _size;
  348.  
  349.    return (tok);
  350.    }
  351.  
  352.  
  353. int find_line_width(int mode, char far *curr, unsigned len)
  354.    {
  355.    int size   = 0,
  356.        width  = 0,
  357.        lwidth = 0,
  358.        done   = 0,
  359.        tok;
  360.  
  361.    do
  362.       {
  363.       tok = find_token_length(mode, curr, len, &size, &width);
  364.  
  365.       switch(tok)
  366.      {
  367.      case TOK_DONE:
  368.      case TOK_PARA:
  369.      case TOK_NL:
  370.      case TOK_FF:
  371.         done = 1;
  372.         break;
  373.  
  374.      case TOK_XONLINE:
  375.      case TOK_XDOC:
  376.      case TOK_CENTER:
  377.         curr += size;
  378.         len -= size;
  379.         break;
  380.  
  381.      default:   /* TOK_SPACE, TOK_LINK or TOK_WORD */
  382.         lwidth += width;
  383.         curr += size;
  384.         len -= size;
  385.         break;
  386.      }
  387.       }
  388.    while ( !done );
  389.  
  390.    return (lwidth);
  391.    }
  392.  
  393.  
  394. #define DO_PRINTN(ch,n)  ( pd.s = &(ch), pd.i = (n), output(PD_PRINTN, &pd, info) )
  395. #define DO_PRINT(str,n)  ( pd.s = (str), pd.i = (n), output(PD_PRINT, &pd, info) )
  396.  
  397.  
  398. int process_document(PD_FUNC get_info, PD_FUNC output, void *info)
  399.    {
  400.    int         skip_blanks;
  401.    int         tok;
  402.    int         size,
  403.          width;
  404.    int         col;
  405.    char      page_text[10];
  406.    PD_INFO   pd;
  407.    char      nl = '\n',
  408.          sp = ' ';
  409.    int         first_section,
  410.          first_topic;
  411.  
  412.    pd.pnum = 1;
  413.    pd.lnum = 0;
  414.  
  415.    col = 0;
  416.  
  417.    output(PD_HEADING, &pd, info);
  418.  
  419.    first_section = 1;
  420.  
  421.    while ( get_info(PD_GET_CONTENT, &pd, info) )
  422.       {
  423.       if ( !output(PD_START_SECTION, &pd, info) )
  424.      return (0);
  425.  
  426.       if ( pd.new_page && pd.lnum != 0 )
  427.      {
  428.      if ( !output(PD_FOOTING, &pd, info) )
  429.         return (0);
  430.      ++pd.pnum;
  431.      pd.lnum = 0;
  432.      if ( !output(PD_HEADING, &pd, info) )
  433.         return (0);
  434.      }
  435.  
  436.       else
  437.      {
  438.      if ( pd.lnum+2 > PAGE_DEPTH-CONTENT_BREAK )
  439.         {
  440.         if ( !output(PD_FOOTING, &pd, info) )
  441.            return (0);
  442.         ++pd.pnum;
  443.         pd.lnum = 0;
  444.         if ( !output(PD_HEADING, &pd, info) )
  445.            return (0);
  446.         }
  447.      else if (pd.lnum > 0)
  448.         {
  449.         if ( !DO_PRINTN(nl, 2) )
  450.            return (0);
  451.         pd.lnum += 2;
  452.         }
  453.      }
  454.  
  455.       if ( !output(PD_SET_SECTION_PAGE, &pd, info) )
  456.      return (0);
  457.  
  458.       if ( !first_section )
  459.      {
  460.      if ( !output(PD_PRINT_SEC, &pd, info) )
  461.         return (0);
  462.      ++pd.lnum;
  463.      }
  464.  
  465.       col = 0;
  466.  
  467.       first_topic = 1;
  468.  
  469.       while ( get_info(PD_GET_TOPIC, &pd, info) )
  470.      {
  471.      if ( !output(PD_START_TOPIC, &pd, info) )
  472.         return (0);
  473.  
  474.      skip_blanks = 0;
  475.      col = 0;
  476.  
  477.      if ( !first_section )     /* do not skip blanks for DocContents */
  478.         {
  479.         while (pd.len > 0)
  480.            {
  481.            tok = find_token_length(DOC, pd.curr, pd.len, &size, NULL);
  482.            if (tok != TOK_XDOC && tok != TOK_XONLINE &&
  483.            tok != TOK_NL   && tok != TOK_DONE )
  484.           break;
  485.            pd.curr += size;
  486.            pd.len  -= size;
  487.            }
  488.         if ( first_topic && pd.len != 0 )
  489.            {
  490.            if ( !DO_PRINTN(nl, 1) )
  491.           return (0);
  492.            ++pd.lnum;
  493.            }
  494.         }
  495.  
  496.      if ( pd.lnum > PAGE_DEPTH-TOPIC_BREAK )
  497.         {
  498.         if ( !output(PD_FOOTING, &pd, info) )
  499.            return (0);
  500.         ++pd.pnum;
  501.         pd.lnum = 0;
  502.         if ( !output(PD_HEADING, &pd, info) )
  503.            return (0);
  504.         }
  505.      else if ( !first_topic )
  506.         {
  507.         if ( !DO_PRINTN(nl, 1) )
  508.            return (0);
  509.         pd.lnum++;
  510.         }
  511.  
  512.      if ( !output(PD_SET_TOPIC_PAGE, &pd, info) )
  513.         return (0);
  514.  
  515.      do
  516.         {
  517.         if ( !output(PD_PERIODIC, &pd, info) )
  518.            return (0);
  519.  
  520.         tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
  521.  
  522.         switch ( tok )
  523.            {
  524.            case TOK_PARA:
  525.           {
  526.           int        indent,
  527.                 margin;
  528.           unsigned  holdlen = 0;
  529.           char far *holdcurr = 0;
  530.           int        in_link = 0;
  531.  
  532.           ++pd.curr;
  533.  
  534.           indent = *pd.curr++;
  535.           margin = *pd.curr++;
  536.  
  537.           pd.len -= 3;
  538.  
  539.           if ( !DO_PRINTN(sp, indent) )
  540.              return (0);
  541.  
  542.           col = indent;
  543.  
  544.           while (1)
  545.              {
  546.              if ( !output(PD_PERIODIC, &pd, info) )
  547.             return (0);
  548.  
  549.              tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
  550.  
  551.              if ( tok == TOK_NL || tok == TOK_FF )
  552.             break;
  553.  
  554.              if ( tok == TOK_DONE )
  555.             {
  556.             if (in_link == 0)
  557.                {
  558.                col = 0;
  559.                ++pd.lnum;
  560.                if ( !DO_PRINTN(nl, 1) )
  561.                   return (0);
  562.                break;
  563.                }
  564.  
  565.             else if (in_link == 1)
  566.                {
  567.                tok = TOK_SPACE;
  568.                width = 1;
  569.                size = 0;
  570.                ++in_link;
  571.                }
  572.  
  573.             else if (in_link == 2)
  574.                {
  575.                tok = TOK_WORD;
  576.                width = strlen(page_text);
  577.                col += 8 - width;
  578.                size = 0;
  579.                pd.curr = page_text;
  580.                ++in_link;
  581.                }
  582.  
  583.             else if (in_link == 3)
  584.                {
  585.                pd.curr = holdcurr;
  586.                pd.len = holdlen;
  587.                in_link = 0;
  588.                continue;
  589.                }
  590.             }
  591.  
  592.              if ( tok == TOK_PARA )
  593.             {
  594.             col = 0;   /* fake a nl */
  595.             ++pd.lnum;
  596.             if ( !DO_PRINTN(nl, 1) )
  597.                return (0);
  598.             break;
  599.             }
  600.  
  601.              if (tok == TOK_XONLINE || tok == TOK_XDOC )
  602.             {
  603.             pd.curr += size;
  604.             pd.len -= size;
  605.             continue;
  606.             }
  607.  
  608.              if ( tok == TOK_LINK )
  609.             {
  610.             pd.s = pd.curr+1;
  611.             if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
  612.                {
  613.                in_link = 1;
  614.                sprintf(page_text, "(p. %d)", pd.i);
  615.                }
  616.             else
  617.                in_link = 3;
  618.             holdcurr = pd.curr + size;
  619.             holdlen = pd.len - size;
  620.             pd.len = size - 8;
  621.             pd.curr += 7;
  622.             continue;
  623.             }
  624.  
  625.              /* now tok is TOK_SPACE or TOK_WORD */
  626.  
  627.              if (col+width > PAGE_WIDTH)
  628.             {       /* go to next line... */
  629.             if ( !DO_PRINTN(nl, 1) )
  630.                return (0);
  631.             if ( ++pd.lnum >= PAGE_DEPTH )
  632.                {
  633.                if ( !output(PD_FOOTING, &pd, info) )
  634.                   return (0);
  635.                ++pd.pnum;
  636.                pd.lnum = 0;
  637.                if ( !output(PD_HEADING, &pd, info) )
  638.                   return (0);
  639.                }
  640.  
  641.             if ( tok == TOK_SPACE )
  642.                width = 0;    /* skip spaces at start of a line */
  643.  
  644.             if ( !DO_PRINTN(sp, margin) )
  645.                return (0);
  646.             col = margin;
  647.             }
  648.  
  649.              if (width > 0)
  650.             {
  651.             if (tok == TOK_SPACE)
  652.                {
  653.                if ( !DO_PRINTN(sp, width) )
  654.                   return (0);
  655.                }
  656.             else
  657.                {
  658.                if ( !DO_PRINT(pd.curr, (size==0) ? width : size) )
  659.                   return (0);
  660.                }
  661.             }
  662.  
  663.              col += width;
  664.              pd.curr += size;
  665.              pd.len -= size;
  666.              }
  667.  
  668.           skip_blanks = 0;
  669.           width = size = 0;
  670.           break;
  671.           }
  672.  
  673.            case TOK_NL:
  674.           if (skip_blanks && col == 0)
  675.              break;
  676.  
  677.           ++pd.lnum;
  678.  
  679.           if ( pd.lnum >= PAGE_DEPTH || (col == 0 && pd.lnum >= PAGE_DEPTH-BLANK_BREAK) )
  680.              {
  681.              if ( col != 0 )    /* if last wasn't a blank line... */
  682.             {
  683.             if ( !DO_PRINTN(nl, 1) )
  684.                return (0);
  685.             }
  686.              if ( !output(PD_FOOTING, &pd, info) )
  687.             return (0);
  688.              ++pd.pnum;
  689.              pd.lnum = 0;
  690.              skip_blanks = 1;
  691.              if ( !output(PD_HEADING, &pd, info) )
  692.             return (0);
  693.              }
  694.           else
  695.              {
  696.              if ( !DO_PRINTN(nl, 1) )
  697.             return (0);
  698.              }
  699.  
  700.           col = 0;
  701.           break;
  702.  
  703.            case TOK_FF:
  704.           if (skip_blanks)
  705.              break;
  706.           if ( !output(PD_FOOTING, &pd, info) )
  707.              return (0);
  708.           col = 0;
  709.           pd.lnum = 0;
  710.           ++pd.pnum;
  711.           if ( !output(PD_HEADING, &pd, info) )
  712.              return (0);
  713.           break;
  714.  
  715.            case TOK_CENTER:
  716.           width = (PAGE_WIDTH - find_line_width(DOC,pd.curr,pd.len)) / 2;
  717.           if ( !DO_PRINTN(sp, width) )
  718.              return (0);
  719.           break;
  720.  
  721.            case TOK_LINK:
  722.           skip_blanks = 0;
  723.           if ( !DO_PRINT(pd.curr+7, size-8) )
  724.              return (0);
  725.           pd.s = pd.curr+1;
  726.           if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
  727.              {
  728.              width += 9;
  729.              sprintf(page_text, " (p. %d)", pd.i);
  730.              if ( !DO_PRINT(page_text, strlen(page_text)) )
  731.             return (0);
  732.              }
  733.           break;
  734.  
  735.            case TOK_WORD:
  736.           skip_blanks = 0;
  737.           if ( !DO_PRINT(pd.curr, size) )
  738.              return (0);
  739.           break;
  740.  
  741.            case TOK_SPACE:
  742.           skip_blanks = 0;
  743.           if ( !DO_PRINTN(sp, width) )
  744.              return (0);
  745.           break;
  746.  
  747.            case TOK_DONE:
  748.            case TOK_XONLINE:   /* skip */
  749.            case TOK_XDOC:       /* ignore */
  750.           break;
  751.  
  752.            } /* switch */
  753.  
  754.         pd.curr += size;
  755.         pd.len  -= size;
  756.         col     += width;
  757.         }
  758.      while (pd.len > 0);
  759.  
  760.      get_info(PD_RELEASE_TOPIC, &pd, info);
  761.  
  762.      first_topic = 0;
  763.      } /* while */
  764.  
  765.       first_section = 0;
  766.       } /* while */
  767.  
  768.    if ( !output(PD_FOOTING, &pd, info) )
  769.       return (0);
  770.  
  771.    return (1);
  772.    }
  773.  
  774. #undef DO_PRINT
  775. #undef DO_PRINTN
  776.  
  777.  
  778. #endif     /* #ifdef INCLUDE_COMMON */
  779.  
  780.  
  781.